﻿namespace ClassyBlog.DataAccess
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;

    using Infrastructure;

    public class PathResolver : IPathResolver
    {
        public PathResolver(IFileSystem fileSystem)
        {
            if (fileSystem == null)
            {
                throw new ArgumentNullException("fileSystem");
            }

            FileSystem = fileSystem;
        }

        protected IFileSystem FileSystem { get; private set; }

        public virtual string Resolve(string dataPath, string relativePath)
        {
            if (string.IsNullOrWhiteSpace(dataPath))
            {
                throw new ArgumentException(
                    TextMessages.Data_Path_Blank, "dataPath");
            }

            if (string.IsNullOrWhiteSpace(relativePath))
            {
                throw new ArgumentException(
                    TextMessages.PathResolver_Resolve_Relative_Path_Blank,
                    "relativePath");
            }

            var absolutePath = MakeAbsolute(dataPath, relativePath);

            var path = Resolve(absolutePath);

            return path;
        }

        public virtual IEnumerable<string> ResolveAll(
            string dataPath,
            string relativePath)
        {
            if (string.IsNullOrWhiteSpace(dataPath))
            {
                throw new ArgumentException(
                    TextMessages.Data_Path_Blank, "dataPath");
            }

            var absolutePath = MakeAbsolute(dataPath, relativePath);

            var paths = ResolveAll(absolutePath);

            return paths;
        }

        private static string MakeAbsolute(
            string dataPath, string relativePath)
        {
            var path = string.IsNullOrWhiteSpace(relativePath) ?
                       dataPath :
                       Path.Combine(dataPath, relativePath);

            path = path.Replace(
                Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);

            return path;
        }

        private string Resolve(string absolutePath)
        {
            var lastIndex = absolutePath.LastIndexOf(
                Path.DirectorySeparatorChar);

            var path = absolutePath.Substring(0, lastIndex);
            var fileName = absolutePath.Substring(lastIndex + 1);

            var pattern = "*" +
                          DataFileConfiguration.Separator +
                          fileName +
                          ".*";

            var filePath = FileSystem.Files(path, pattern, false)
                                     .FirstOrDefault();

            return filePath;
        }

        private IEnumerable<string> ResolveAll(string absolutePath)
        {
            var pattern = "*" + DataFileConfiguration.Separator + "*.*";
            var hiddenPrefix = DataFileConfiguration.HiddenPrefix.ToString();

            Func<string, bool> filter = p =>
                !(Path.GetFileName(p) ?? string.Empty).
                StartsWith(hiddenPrefix, StringComparison.Ordinal);

            var filePaths = FileSystem.Files(absolutePath, pattern, false)
                                      .Where(filter);

            return filePaths;
        }
    }
}